/*
 * Engranaje.cpp
 *
 *  Created on: 08/10/2013
 *      Author: juliansci
 */

#include <iostream>
#include "Engranaje.h"

Engranaje::Engranaje(double x, double y, double ancho, double alto,
		string pathImagen) :
		Elemento(x, y, ancho, alto, pathImagen) {
	this->elementoUnido = NULL;
	this->posCorreaX = (ancho) / 2;
	this->posCorreaY = (alto * 4) / 5;
	this->correaUnida = NULL;
	this->correaInicial = true;
	this->estaAndando = false;
	this->listaEngranajesAsociados = new list<Elemento*>;
}

Engranaje::~Engranaje() {
}

int Engranaje::seSuperpone(Elemento* elemento) {
	if (elemento->getTipo() == "correa")
		return 0;
	if (elemento->getTipo() == "engranaje")
		return 1;
	if (!elemento->aceptaEngranaje())
		return 2;
	return 1;
}

void Engranaje::superponer(Elemento* elemento) {
	if (elemento->getTipo() == "motor") {
		elemento->agregarEngranaje(this);
		this->elementoUnido = elemento;
	} else if (elemento->getTipo() == "cinta") {
		elemento->agregarEngranaje(this);
		this->elementoUnido = elemento;
	} else if (elemento->getTipo() == "engranaje") {
		elemento->agregarEngranaje(this);
		cout << "SE LO AGREGUE" << endl;
		this->listaEngranajesAsociados->push_back(elemento);
		cout << "SE LO AGREGUE 2" << endl;
	}
}

void Engranaje::mover(double centroX, double centroY) {
	Elemento::mover(centroX, centroY);
	if (this->elementoUnido != NULL) {
		this->elementoUnido->eliminarEngranaje();
		this->elementoUnido = NULL;
	}
	this->actualizarPosicionCorrea();
}

Elemento* Engranaje::obtenerCorrea(){
	return this->correaUnida;
}


void Engranaje::agregarCorreaInicial(Elemento* correa) {
	correa->setPosicionInicial(this->getX() + this->posCorreaX,
			this->getY() + this->posCorreaY);
	this->correaUnida = correa;
	this->correaInicial = true;
}

void Engranaje::agregarCorreaFinal(Elemento* correa) {
	correa->setPosicionFinal(this->getX() + this->posCorreaX,
			this->getY() + this->posCorreaY);
	this->correaUnida = correa;
	this->correaInicial = false;
}

void Engranaje::actualizarPosicionCorrea() {
	if (this->correaUnida != NULL) {
		cout << "tiene correa unidaa!!!" << endl;
		if (this->correaInicial) {
			this->correaUnida->setPosicionInicial(
					this->getX() + this->posCorreaX,
					this->getY() + this->posCorreaY);
		} else {
			this->correaUnida->setPosicionFinal(this->getX() + this->posCorreaX,
					this->getY() + this->posCorreaY);
		}
	}
}

bool Engranaje::aceptaCorrea() {
	if (this->correaUnida)
		return false;
	return true;
}

void Engranaje::eliminarCorrea() {
	this->correaUnida = NULL;
}

void Engranaje::agregarMotor(Elemento* motor) {
	this->elementoUnido = motor;
}

void Engranaje::eliminarReferencias(list<Elemento*>* elementosCanvas) {
	cout << "Entro a eliminar referencias del engranaje" << endl;

	list<Elemento*>::iterator itElementos = elementosCanvas->begin();
	while (itElementos != elementosCanvas->end()) {
		Elemento* elemento = (*itElementos);
		if (elemento->getTipo().compare("motor") == 0
				&& (elemento->obtenerEngranaje()) == this) {
			cout << "Elimino el engranaje del motor" << endl;
			elemento->eliminarEngranaje();
		} else if (elemento->getTipo().compare("cinta") == 0
				&& (elemento->obtenerEngranaje()) == this) {
			cout << "Elimino el engranaje de la cinta" << endl;
			elemento->eliminarEngranaje();
		} else if (elemento->getTipo().compare("engranaje") == 0
				&& (elemento->engranajeEnLista(this)) == true) {
			cout << "Elimino el engranaje de su engranaje asociado" << endl;
			elemento->eliminarEngranajeDeLista(this);
		}
		itElementos++;
	}

	pair<Elemento*, Elemento*> extremosCorrea;
	if (this->correaUnida) {
		cout << "Entro al IF de la correa unida" << endl;
		elementosCanvas->remove(this->correaUnida);
		extremosCorrea = this->correaUnida->obtenerExtremos();
		delete this->correaUnida;
		extremosCorrea.first->eliminarCorrea();
		extremosCorrea.second->eliminarCorrea();
	}
	cout << "fin eliminar referencias engraNAJE! " << endl;

}

bool Engranaje::asociadoAMotor() {
	cout << "engggranaje con id: " << this->getIdElemento()
			<< " en metodo de tiene motor" << endl;
	if (this->elementoUnido) {
		if (this->elementoUnido->getTipo() == "motor") {
			return true;
		}
	}
	return false;
}

bool Engranaje::asociadoACorreaConMotor() {
	if (this->correaUnida) {
		pair<Elemento*, Elemento*> extremosCorrea =
				this->correaUnida->obtenerExtremos();
		Engranaje* engranaje1 = (Engranaje*) extremosCorrea.first;
		Engranaje* engranaje2 = (Engranaje*) extremosCorrea.second;
		if (engranaje1->asociadoAMotor())
			return true;
		if (engranaje2->asociadoAMotor())
			return true;
	}
	return false;
}

bool Engranaje::chequearIngresoCinta(Elemento* cinta) {

	if (cinta->obtenerEngranaje() == NULL) {
		this->superponer(cinta);
		return true;
	}

	return false;
}

void Engranaje::agregarEngranaje(Elemento* engranaje) {
	cout << "VOY A AGREGARLE UN ENGRANAJE AL ENGRANAJE " << endl;

//	double distanciaY = (engranaje->getY()+engranaje->getAlto()/2) -
//			(this->getY()+this->getAlto()/2);
//	double distanciaX = (engranaje->getX()+engranaje->getAncho()/2) -
//			(this->getX()+this->getAncho()/2);
//
////	cout << "Centro Engranaje en canvas: (" <<
//	double angulo = -atan2(distanciaY,distanciaX);
//
//	double radioEngranaje = this->getAncho()/2;
//	double radioEngranajeSuperpuesto = engranaje->getAncho()/2;
//
//	double longX = (radioEngranaje + radioEngranajeSuperpuesto) * cos(angulo);
//
//	cout << "radio engranaje: " << radioEngranaje <<
//			" radio engranaje superpuesto: " << radioEngranajeSuperpuesto << endl;
//
//	double longY = (radioEngranaje + radioEngranajeSuperpuesto) * sin(angulo);
//
//	longY = longY + engranaje->getAlto()/2;
//
//	cout << "Longitud Y: " << longY << endl;
//
//	double posYEngranaje = this->getY() + this->getAlto()/2 - longY ;
//	double posXEngranaje = this->getX() - this->getAncho()/2 + longX ;
//
//
//	cout << "Angulo entre engranajes: " << angulo*180/3.141628 << endl;
//
//	cout << "Longitud x: " << longX << endl;
//
//	engranaje->setX(posXEngranaje);
//	//engranaje->setY(engranaje->getY() + 5);
//	engranaje->setY(posYEngranaje);

	this->listaEngranajesAsociados->push_back(engranaje);
	cout << "AGREGUE" << endl;
}

void Engranaje::eliminarEngranajeDeLista(Elemento* engranaje) {
	this->listaEngranajesAsociados->remove(engranaje);
}

bool Engranaje::engranajeEnLista(Elemento* elemento) {

	list<Elemento*>::iterator itLista = this->listaEngranajesAsociados->begin();
	for (; itLista != this->listaEngranajesAsociados->end(); itLista++) {
		Elemento * elementoLista = (*itLista);
		if (elementoLista == elemento) {
			return true;
		}
	}
	return false;
}

void Engranaje::jointearElemento(b2World* world) {
	if (this->listaEngranajesAsociados->size()>0){
		EngranajeFisica* entidadFisicaEngranajePropio = (EngranajeFisica*)this->getEntidadFisica();
		list<Elemento*>::iterator itListaEngranajes = this->listaEngranajesAsociados->begin();
		Elemento* engranajeActual;
		EntidadFisica* entidadFisicaActual;
		cout << "Estoy uniendo elementos para el joint del engranaje" << endl;
		int i = 0;
		for(;itListaEngranajes != this->listaEngranajesAsociados->end() ; ++itListaEngranajes){
			i++;
			engranajeActual = *itListaEngranajes;
			entidadFisicaActual = engranajeActual->getEntidadFisica();
			entidadFisicaEngranajePropio->agregarEngranajeAConectar(entidadFisicaActual);
		}
		entidadFisicaEngranajePropio->jointear(world);
		cout << "entra i veces: " << i << endl;
	}
}

list<Elemento*>* Engranaje::obtenerListaEngranajesAsociados(){
	return this->listaEngranajesAsociados;
}

